﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sohobloo.SoMcCoffee.Entity;

namespace Mojito.WebSite.Models
{
    public class ViewModelBase
    {
        #region Static Method
        /// <summary>
        /// Deserialize a json string to the specific object type
        /// ***CAUTION:ONLY COMPATIBLE WITH SIMPLE OBJECT***
        /// </summary>
        /// <typeparam name="T">the specific object type</typeparam>
        /// <param name="json">json string</param>
        /// <returns>the specific typed object</returns>
        public static T FromJSON<T>(string json)
        {
            MemoryStream ms = null;
            T obj;
            try
            {
                ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
                var serializer = new DataContractJsonSerializer(typeof(T));
                obj = (T)serializer.ReadObject(ms);
            }
            finally
            {
                if (ms != null)
                {
                    ms.Close();
                }
            }
            return obj;
        }

        #endregion

        public ViewModelBase() { }

        public ViewModelBase(EntityBase entity)
        {
            this.FromEntity(entity);
        }

        /// <summary>
        /// Serialize current object to a json string
        /// </summary>
        /// <returns>the serialized json string</returns>
        protected virtual string ToJSON()
        {
            return JsonConvert.SerializeObject(this);
        }

        protected virtual void FromEntity<T>(T entity) where T : EntityBase
        {
            if(entity == null) return;
            foreach (PropertyInfo targetProperty in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                PropertyInfo sourceProperty = entity.GetType().GetProperty(targetProperty.Name);

                if (targetProperty.CanWrite && sourceProperty.CanRead &&
                    ((targetProperty.GetSetMethod().Attributes & MethodAttributes.Static) == 0) &&
                    targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
                {
                    targetProperty.SetValue(this, sourceProperty.GetValue(entity, null), null);
                }
            }
        }

        #region Property
        public Guid Id { get; set; }
        public DataStatus DataStatus { get; set; }
        public long SortIndex { get; set; }
        #endregion
    }
}